package com.jz.banner.screen.ui.activity.base

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.view.KeyEvent
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import butterknife.ButterKnife
import butterknife.Unbinder
import com.alibaba.android.arouter.launcher.ARouter
import com.gyf.barlibrary.ImmersionBar
import com.jz.banner.screen.R
import com.jz.banner.screen.ui.App
import com.jz.banner.screen.ui.activity.LoginActivity
import com.jz.banner.screen.utils.*
import com.jz.banner.screen.utils.eventbus.Event
import com.jz.banner.screen.utils.eventbus.EventBusUtil
import com.jz.banner.screen.utils.eventbus.EventCode
import com.jz.banner.screen.widget.dialog.LoadingDialog
import com.jz.banner.screen.widget.statueslayoutmanager.DefaultOnStatusChildClickListener
import com.jz.banner.screen.widget.statueslayoutmanager.StatusLayoutManager
import com.trello.rxlifecycle2.components.support.RxAppCompatActivity
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.lang.reflect.Method
import kotlin.system.exitProcess


/**
 * 创建者     Noel
 * 创建时间   2017/12/20 17:22
 */
abstract class BaseActivity : RxAppCompatActivity() {

    /*Log信息的标记*/
    private var mLogTag = javaClass.simpleName

    protected open fun doubleQuit(): Boolean = false
    protected open var MSG_EXIT = 1
    protected open var isExit: Boolean = false
    protected open val mHandler: Handler by lazy {
        @SuppressLint("HandlerLeak") object : Handler() {
            override fun handleMessage(msg: Message) {
                if (msg.what == MSG_EXIT) isExit = false
            }
        }
    }
    protected val mLoadingDialog: LoadingDialog by lazy {
        LoadingDialog(this)
    }

    protected var mImmersionBar: ImmersionBar? = null
    private var imm: InputMethodManager? = null
    private var unBinder: Unbinder? = null

    val mStatusLayoutManager: StatusLayoutManager by lazy {
        StatusLayoutManager.Builder(getRootLayout())
            .setLoadingLayout(R.layout.layout_status_layout_manager_loading)
            .setDefaultErrorClickViewVisible(setDefaultErrorClickViewVisible)
            .setDefaultEmptyClickViewVisible(setDefaultEmptyClickViewVisible)
            .setOnStatusChildClickListener(object : DefaultOnStatusChildClickListener() {
                override fun onEmptyChildClick(view: View?) {
                    onEmptyChildClick()
                }

                override fun onErrorChildClick(view: View?) {
                    onErrorChildClick()
                }
            })
            .build()
    }

    /*基于那个视图上 放一个 加载页或者错误、空白页面。*/
    open fun getRootLayout(): View = View(this)

    protected var setDefaultErrorClickViewVisible = true
    protected var setDefaultEmptyClickViewVisible = false
    open fun onEmptyChildClick() {}
    open fun onErrorChildClick() {}

    override fun onCreate(savedInstanceState: Bundle?) {
        if (Urls.updateType == Urls.SIGN_UPDATE_TYPE_BY_SHELL_INSTALL_JGL) hookWebView()
        super.onCreate(savedInstanceState)
        beforeSetContentView()
        ActivityCollector.addActivity(this)
        if (App.flag == -1) {
            protectApp()
        } else {
            setLayout(getContentLayout())
            if (isRegisterEventBus()) EventBusUtil.register(this)
            unBinder = ButterKnife.bind(this)
            getIntentInfo()
            //初始化沉浸式
            initImmersionBar()
            initOther()
            initView()
            initData()
            initListener()
        }
    }

    /*重启 app*/
    protected open fun protectApp() {
//        d("protectApp??")
        val intent = Intent(this, LoginActivity::class.java) //为啥启动IndexActivity,因为他是singleTask,
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) //清空栈里MainActivity之上的所有activty
        startActivity(intent)
        finish()
        overridePendingTransition(0, 0)
    }

    protected open fun isRegisterEventBus(): Boolean = false

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventBusCome(event: Event<Any>?) {
        if (event != null) receiveEvent(event = event)
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    fun onStickyEventBusCome(event: Event<Any>?) {
        if (event != null) receiveStickyEvent(event = event)
    }

    //eventbust 一个带粘性一个不带。
    protected open fun receiveEvent(event: Event<Any>) {}

    protected open fun receiveStickyEvent(event: Event<Any>) {}


    /*在获取子类视图之前的操作，例如设置键盘*/
    protected open fun beforeSetContentView() {}

    /*获取子类的视图*/
    abstract fun getContentLayout(): Any

    private fun setLayout(any: Any) {
        when (any) {
            is View -> super.setContentView(any)
            is Int -> super.setContentView(any)
        }
    }

    protected open fun initOther() {}
    abstract fun initView()
    abstract fun initData()
    abstract fun initListener()

    protected open fun getIntentInfo() {}

    override fun onDestroy() {
        mLoadingDialog.dismiss()
        this.imm = null
        mImmersionBar?.destroy()  //在BaseActivity里销毁
        if (isRegisterEventBus()) EventBusUtil.unregister(this)
        ActivityCollector.removeActivity(this)
        super.onDestroy()
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (doubleQuit() && keyCode == KeyEvent.KEYCODE_BACK) return exit()
        return super.onKeyDown(keyCode, event)
    }

    protected open fun exit(): Boolean {
        if (!isExit) {
            isExit = true
            ToastUtil.showToast(getString(R.string.exit_str))
            // 利用handler延迟发送更改状态信息
            mHandler.sendEmptyMessageDelayed(MSG_EXIT, 2000)
        } else {
            finish()
            exitProcess(0)
//            ActivityCollector.finishAll()
        }
        return false
    }

    //dialog
    fun show() {
        show("正在加载..")
    }

    fun show(title: String) {
        if (!mLoadingDialog.isShowing) {
            mLoadingDialog.show() //先show,才能设置title，否则titleTv还没初始化。
            mLoadingDialog.setTitleTv(title)
        }
    }

    fun dismiss() {
        if (mLoadingDialog.isShowing) mLoadingDialog.dismiss()
    }

    fun d(msg: String) {
        CommUtils.println("$mLogTag->", msg)
    }

    protected open fun goBack() {
        finish()
    }


    protected open fun initImmersionBar() {
        //在BaseActivity里初始化
        mImmersionBar = ImmersionBar.with(this)
        mImmersionBar!!.init()
    }

    /**
     * 是否可以使用沉浸式
     * Is immersion bar enabled boolean.
     *
     * @return the boolean true 使用immersion ，false，使用原有方法（自己创建）。
     */

    override fun finish() {
        try {
            hideSoftKeyBoard()
            unBinder?.unbind()
        } catch (e: Exception) {

        }
        super.finish()
    }

    protected fun go2LoginScreen() {
        ARouter.getInstance()
            .build(ARouterUtils.LoginActivity)
            .navigation()
        finish()
    }

    fun initScanner(et: EditText) {
        //获得光标
        et.isFocusable = true
        et.isFocusableInTouchMode = true
        et.requestFocus()
        val manager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
        manager.hideSoftInputFromWindow(if (et == null) null else et.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
        et.setOnKeyListener { v, keyCode, event ->
            d("initScanner::keyCode::${keyCode},event.action:${event.action}")
            if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_DOWN) {
                val cardNumber = et.text.toString()
                d("initScanner::CardStr::$cardNumber")
                EventBusUtil.sendEvent(Event(EventCode.HANDLE_SWING_CARD, cardNumber))
                false
            } else if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP) {
                et.setText("")
                true
            }
            false
        }
    }

    fun hideSoftKeyBoard() {
        val localView = currentFocus
        if (this.imm == null) {
            this.imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        }
        if (localView != null && this.imm != null) {
            this.imm!!.hideSoftInputFromWindow(localView.windowToken, 2)
        }
    }

    //Android Webview在系统签名下会崩溃报错的解决方案
    open fun hookWebView() {
        val sdkInt = Build.VERSION.SDK_INT
        try {
            val factoryClass = Class.forName("android.webkit.WebViewFactory")
            val field = factoryClass.getDeclaredField("sProviderInstance")
            field.isAccessible = true
            var sProviderInstance = field[null]
            if (sProviderInstance != null) {
                CommUtils.Companion.println("hookWebView:", "sProviderInstance isn't null")
                return
            }
            val getProviderClassMethod: Method
            getProviderClassMethod = if (sdkInt > 22) {
                factoryClass.getDeclaredMethod("getProviderClass")
            } else if (sdkInt == 22) {
                factoryClass.getDeclaredMethod("getFactoryClass")
            } else {
                CommUtils.Companion.println("hookWebView:", "Don't need to Hook WebView")
                return
            }
            getProviderClassMethod.isAccessible = true
            val providerClass = getProviderClassMethod.invoke(factoryClass) as Class<*>
            val delegateClass = Class.forName("android.webkit.WebViewDelegate")
            val providerConstructor = providerClass.getConstructor(delegateClass)
            if (providerConstructor != null) {
                providerConstructor.isAccessible = true
                val declaredConstructor = delegateClass.getDeclaredConstructor()
                declaredConstructor.isAccessible = true
                sProviderInstance = providerConstructor.newInstance(declaredConstructor.newInstance())
                CommUtils.Companion.println("hookWebView:", "sProviderInstance:{} $sProviderInstance")
                field["sProviderInstance"] = sProviderInstance
            }
            CommUtils.Companion.println("hookWebView:", "Hook done!")
        } catch (e: Throwable) {
            CommUtils.Companion.println("hookWebView:", e.toString())
        }
    }
}

